"""
多个线程竞争一个资源 ---> 临界资源
想要保护资源（在关键操作上只有一个线程能够访问到这个资源）需要使用锁
"""
import random
import time
from concurrent.futures.thread import ThreadPoolExecutor
from threading import RLock, current_thread, Condition


class Account:
    """银行账户"""

    def __init__(self):
        self.balance = 0
        self.condition = Condition(RLock())

    def deposit(self, money):
        """存钱
        :param money: 存入的金额
        """
        # self.lock.acquire() ---> 获得锁
        with self.condition:
            new_balance = self.balance + money
            time.sleep(0.01)
            self.balance = new_balance
            # 唤醒（通知）暂停的线程让它们有机会恢复执行
            self.condition.notify_all()
        # self.lock.release() ---> 释放锁

    def withdraw(self, money):
        """取钱
        :param money: 取款的金额
        :return: 取款成功返回True，否则返回False
        """
        with self.condition:
            while self.balance < money:
                # 如果线程执行条件不满足，可以让线程暂停并释放已经获得的锁对象
                self.condition.wait()
            new_balance = self.balance - money
            time.sleep(0.01)
            self.balance = new_balance


def put_money(account):
    while True:
        money = random.randint(5, 10)
        account.deposit(money)
        print(f'{current_thread().name}存入{money}元, 当前余额{account.balance}元')
        time.sleep(1)


def get_money(account):
    while True:
        money = random.randint(10, 20)
        account.withdraw(money)
        print(f'{current_thread().name}取出{money}元, 当前余额{account.balance}元')
        time.sleep(0.5)


def main():
    account = Account()
    with ThreadPoolExecutor(max_workers=10) as pool:
        for _ in range(5):
            pool.submit(put_money, account)
            pool.submit(get_money, account)


if __name__ == '__main__':
    main()
